home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 8: LINUX Games / Linux Cubed Series 8 - LINUX Games.iso / games / muds / pennmush.000 / pennmush-1.50-p8-linux.tar / pennmush / set.c < prev    next >
C/C++ Source or Header  |  1993-04-06  |  26KB  |  1,049 lines

  1. /* set.c */
  2.  
  3. #include "copyright.h"
  4.  
  5. /* commands which set parameters */
  6. #include <stdio.h>
  7. #include <ctype.h>
  8. #include <string.h>
  9. #include <sys/time.h>
  10. #include <sys/types.h>
  11.  
  12. #include "config.h"
  13. #include "db.h"
  14. #include "match.h"
  15. #include "interface.h"
  16. #include "externs.h"
  17.  
  18. extern void set_flag();        /* from flags.c */
  19.  
  20. #ifdef NOCRYPT
  21. char *crypt(s, t)
  22.     char *s, *t;
  23. {
  24.   /* the DES encryption scheme cannot be exported outside the United States.
  25.    * Thus, this function is needed because the crypt() library function
  26.    * does not exist.
  27.    */
  28.   return (s);
  29. }
  30. #endif
  31.  
  32. void do_name(player, name, newname)
  33.     dbref player;
  34.     const char *name;
  35.     char *newname;
  36. {
  37.   dbref thing;
  38.   char *password;
  39. #ifdef RWHO_SEND
  40.   char tbuf1[BUFFER_LEN];
  41. #endif
  42.  
  43.   if ((thing = match_controlled(player, name)) != NOTHING) {
  44.     /* check for bad name */
  45.     if (*newname == '\0') {
  46.       notify(player, "Give it what new name?");
  47.       return;
  48.     }
  49.     /* check for renaming a player */
  50.     if (Typeof(thing) == TYPE_PLAYER) {
  51. #ifdef GUEST_RESTRICT
  52.       if (Guest(player)) {
  53.     notify(player, "Guests may not rename themselves.");
  54.     return;
  55.       }
  56. #endif
  57.       /* split off password */
  58.       for (password = newname;
  59.        *password && !isspace(*password);
  60.        password++) ;
  61.       /* eat whitespace */
  62.       if (*password) {
  63.     *password++ = '\0';    /* terminate name */
  64.     while (*password && isspace(*password))
  65.       password++;
  66.       }
  67.       /* check for null password */
  68.       if (!*password) {
  69.     notify(player,
  70.            "You must specify a password to change a player name.");
  71.     notify(player, "E.g.: name player = newname password");
  72.     return;
  73.       } else if (!password_check(thing, password)) {
  74.     notify(player, "Incorrect password.");
  75.     return;
  76.       } else if (strcasecmp(newname, db[player].name)
  77.          && !ok_player_name(newname)) {
  78.     /* strcasecmp allows changing foo to Foo, etc. */
  79.     notify(player, "You can't give a player that name.");
  80.     return;
  81.       }
  82.       /* everything ok, notify */
  83.       do_log(LT_CONN, 0, 0, "Name change by %s(#%d) to %s",
  84.          Name(thing), thing, newname);
  85.       fflush(connlog_fp);
  86.       if (Suspect(thing))
  87.     raw_broadcast(WIZARD, "Broadcast: Suspect %s changed name to %s.",
  88.               Name(thing), newname);
  89. #ifdef RWHO_SEND      
  90.       sprintf(tbuf1, "%d@%s", thing, MUDNAME);
  91.       rwhocli_userlogout(tbuf1); 
  92. #endif
  93.       delete_player(thing, NULL);
  94.       SET(Name(thing), newname);
  95.       add_player(thing, NULL);
  96. #ifdef RWHO_SEND
  97.       rwhocli_userlogin(tbuf1, newname, time((time_t *) 0));
  98. #endif
  99.       notify(player, "Name set.");
  100.       return;
  101.     } else {
  102.       if (!ok_name(newname)) {
  103.     notify(player, "That is not a reasonable name.");
  104.     return;
  105.       }
  106.     }
  107.  
  108.     /* everything ok, change the name */
  109.     SET(Name(thing), newname);
  110.     notify(player, "Name set.");
  111.   }
  112. }
  113.  
  114. static void do_alias(player, thing, attrib, alias)
  115.      dbref player;
  116.      dbref thing;
  117.      ATTR *attrib;
  118.      const char *alias;
  119. {
  120.     /* Set the alias attribute on a player. A controls check has already
  121.      * been done.
  122.      */
  123.  
  124.     ATTR *temp;
  125.     char tbuf1[PLAYER_NAME_LIMIT];
  126.  
  127.     if (Typeof(thing) != TYPE_PLAYER) {
  128.     /* The attribute doesn't do anything special. Just set it. */
  129.     atr_add(thing, attrib->name, alias, player, attrib->flags);
  130.     if (!Quiet(player) && !Quiet(thing))
  131.         notify(player, tprintf("%s - Set.", Name(thing)));
  132.     return;
  133.     }
  134.  
  135.     if (*alias == '\0') {
  136.     /* Alias deletion. */
  137.     if ((temp = atr_get_noparent(thing, "ALIAS")) == NULL) {
  138.         notify(player, "No alias to remove.");
  139.         return;
  140.     } else {
  141.         strcpy(tbuf1, uncompress(temp->value));
  142.         delete_player(thing, tbuf1);
  143.         atr_add(thing, attrib->name, "", player, attrib->flags);
  144.         notify(player, "Alias removed.");
  145.         return;
  146.     }
  147.     }
  148.  
  149.     if (!ok_player_name(alias)) {
  150.     notify(player, "That is not a valid alias.");
  151.     return;
  152.     }
  153.  
  154.     if ((temp = atr_get_noparent(thing, "ALIAS")) != NULL) {
  155.     /* We have to delete the old alias before adding the new one. */
  156.     strcpy(tbuf1, uncompress(temp->value));
  157.     delete_player(thing, tbuf1);
  158.     }
  159.  
  160.     /* Add the new alias. */
  161.     add_player(thing, alias);
  162.     atr_add(thing, attrib->name, alias, player, attrib->flags);
  163.     notify(player, "Alias set.");
  164. }
  165.  
  166.  
  167. void do_unlock(player, name, locktype)
  168.     dbref player;
  169.     const char *name;
  170.     int locktype;
  171. {
  172.   dbref thing;
  173.   char *sp;
  174.  
  175.   /* check for '@unlock <object>/<atr>'  */
  176.   sp = (char *) index(name, '/');
  177.   if (sp) {
  178.     do_atrlock(player, name, "off");
  179.     return;
  180.   }
  181.  
  182.   if ((thing = match_controlled(player, name)) != NOTHING) {
  183.     switch (locktype) {
  184.     case BASICLOCK:
  185.       free_boolexp(db[thing].key);
  186.       db[thing].key = TRUE_BOOLEXP;
  187.       break;
  188.     case USELOCK:
  189.       free_boolexp(db[thing].usekey);
  190.       db[thing].usekey = TRUE_BOOLEXP;
  191.       break;
  192.     case ENTERLOCK:
  193.       free_boolexp(db[thing].enterkey);
  194.       db[thing].enterkey = TRUE_BOOLEXP;
  195.       break;
  196.     }
  197.     notify(player, "Unlocked.");
  198.   }
  199. }
  200.  
  201. void do_lock(player, name, keyname, locktype)
  202.     dbref player;
  203.     const char *name;
  204.     const char *keyname;
  205.     int locktype;
  206. {
  207.   dbref thing;
  208.   struct boolexp *key;
  209.   char *sp;
  210.  
  211.   if (!keyname || !*keyname) {
  212.       do_unlock(player, name, locktype);
  213.       return;
  214.   }
  215.  
  216.   /* check for '@lock <object>/<atr>'  */
  217.   sp = (char *) index(name, '/');
  218.   if (sp) {
  219.     do_atrlock(player, name, "on");
  220.     return;
  221.   }
  222.  
  223.   init_match(player, name, NOTYPE);
  224.   match_everything();
  225.  
  226.   switch (thing = match_result()) {
  227.     case NOTHING:
  228.       notify(player, "I don't see what you want to lock!");
  229.       return;
  230.     case AMBIGUOUS:
  231.       notify(player, "I don't know which one you want to lock!");
  232.       return;
  233.     default:
  234.       if (!controls(player, thing)) {
  235.     notify(player, "You can't lock that!");
  236.     return;
  237.       }
  238.       if (Flags(thing) & GOING) {
  239.     notify(player, "Why would you want to lock garbage?");
  240.     return;
  241.       }
  242.       break;
  243.   }
  244.  
  245.   key = parse_boolexp(player, keyname);
  246.  
  247.   /* do the lock */
  248.   if (key == TRUE_BOOLEXP) {
  249.     notify(player, "I don't understand that key.");
  250.   } else {
  251.     /* everything ok, do it */
  252.     switch (locktype) {
  253.     case BASICLOCK:
  254.       free_boolexp(db[thing].key);
  255.       db[thing].key = key;
  256.       break;
  257.     case USELOCK:
  258.       free_boolexp(db[thing].usekey);
  259.       db[thing].usekey = key;
  260.       break;
  261.     case ENTERLOCK:
  262.       free_boolexp(db[thing].enterkey);
  263.       db[thing].enterkey = key;
  264.       break;
  265.     }
  266.     notify(player, "Locked.");
  267.   }
  268. }
  269.  
  270. void do_chown(player, name, newobj)
  271.     dbref player;
  272.     const char *name;
  273.     const char *newobj;
  274. {
  275.     dbref thing;
  276.     dbref owner = NOTHING;
  277.     char *sp;
  278.  
  279.     /* check for '@chown <object>/<atr>=<player>'  */
  280.     sp = (char *) index(name, '/');
  281.     if (sp) {
  282.     do_atrchown(player, name, newobj);
  283.     return;
  284.     }
  285.  
  286.     init_match(player, name, TYPE_THING);
  287.     match_possession();
  288.     match_here();
  289.     match_exit();
  290.     if(Wizard(player)) {
  291.     match_player();
  292.     match_absolute();
  293.     }
  294.  
  295.     if ((thing = noisy_match_result()) == NOTHING)
  296.     return;
  297.  
  298.     if (!*newobj || !strcasecmp(newobj, "me")) {
  299.     owner = player;
  300.     } else {
  301.         if ((owner = lookup_player(newobj)) == NOTHING) {
  302.         notify(player, "I couldn't find that player.");
  303.         return;
  304.         }
  305.     }
  306.  
  307.     if (Typeof(thing) == TYPE_PLAYER && !God(player)) {
  308.     notify(player, "Players always own themselves.");
  309.     return;
  310.     }
  311.  
  312.     /* in order to @chown an object, must fit one of the following:
  313.      *
  314.      *   1.  player is a wizard
  315.      *   2.  player owns the thing or controls the owner of the thing
  316.      *   3.  thing is CHOWN_OK, and the player is holding the object.
  317.      *
  318.      * The player must also control the person who is receiving
  319.      * ownership of the object.
  320.      *
  321.      * There is another possibility: chowning to a Zone Master. In
  322.      * this case the player still has to own the thing or have it 
  323.      * CHOWN_OK, but only needs to pass the enter (control) lock of
  324.      * the Zone Master. This is automatically covered by the controls
  325.      * check, though. We do have to check for getting stuff out of a 
  326.      * ZoneMaster's ownership, though.
  327.      *
  328.      */
  329.  
  330.     if (!(Wizard(player) ||
  331.       ((Owns(player, thing) || 
  332.         ((Flags(thing) & CHOWN_OK) &&
  333.          ((Typeof(thing) != TYPE_THING) || (Location(thing) == player))) ||
  334.         (ZMaster(Owner(thing)) &&
  335.          eval_boolexp(player, Enterkey(Owner(thing)), thing,
  336.               0, ENTERLOCK))) &&
  337.        controls(player, owner)))) {
  338.     notify(player, "Permission denied.");
  339.     return;
  340.     }
  341.  
  342.  
  343.     /* chowns on the zone master don't count towards fees */
  344.     if (!ZMaster(owner) && !ZMaster(Owner(thing))) {
  345.     if (!can_pay_fees(player, OBJECT_COST)) /* not enough money or quota */
  346.         return;
  347.     giveto(Owner(thing), OBJECT_COST);
  348. #ifdef QUOTA
  349.     change_quota(Owner(thing), QUOTA_COST);
  350. #endif
  351.     }
  352.  
  353.     if (God(player)) {
  354.     Owner(thing) = owner;
  355.     } else {
  356.     Owner(thing) = Owner(owner);
  357.     }
  358.     Zone(thing) = Zone(owner);
  359.     Flags(thing) &= ~CHOWN_OK;
  360.     Flags(thing) &= ~WIZARD;
  361. #ifdef ROYALTY_FLAG
  362.     Flags(thing) &= ~ROYALTY;
  363. #endif
  364.     Flags(thing) &= ~INHERIT;
  365.     Flags(thing) |= HALT;
  366.     Powers(thing) = 0;    /* wipe out all powers */
  367.     notify(player, "Owner changed.");
  368. }
  369.  
  370.  
  371. void do_chzone(player, name, newobj)
  372.      dbref player;
  373.      const char *name;
  374.      const char *newobj;
  375. {
  376.   dbref thing;
  377.   dbref zone;
  378.  
  379.   init_match(player, name, NOTYPE);
  380.   match_nearby();
  381.   if ((thing = noisy_match_result()) == NOTHING)
  382.     return;
  383.  
  384.   if (!strcasecmp(newobj, "none"))
  385.     zone = NOTHING;
  386.   else {
  387.     init_match(player, newobj, NOTYPE);
  388.     match_here();
  389.     match_neighbor();
  390.     match_possession();
  391.     match_absolute();
  392.     if ((zone = noisy_match_result()) == NOTHING)
  393.       return;
  394.  
  395.     if ((Typeof(zone) != TYPE_THING)
  396. #ifdef DO_GLOBALS
  397.     && (Typeof(zone) != TYPE_ROOM)
  398. #endif
  399.     ) {
  400.       notify(player, "Invalid zone object type.");
  401.       return;
  402.     }
  403.   }
  404.  
  405.   /* we do use ownership instead of control as a criterion because
  406.    * we only want the owner to be able to rezone the object. Also,
  407.    * this allows players to @chzone themselves to an object they own.
  408.    */
  409.   if (!Wizard(player) && !Owns(player, thing)) {
  410.     notify(player, "You don't have the power to shift reality.");
  411.     return;
  412.   }
  413.  
  414.   /* a player may change an object's zone to NOTHING or to an object he owns */
  415.   if ((zone != NOTHING) && !Wizard(player) &&
  416.       !Owns(player, zone)) {
  417.     notify(player, "You cannot move that object to that zone.");
  418.     return;
  419.   }
  420.  
  421.   /* only rooms may be zoned to other rooms */
  422.   if ((zone != NOTHING) &&
  423.       (Typeof(zone) == TYPE_ROOM) && Typeof(thing) != TYPE_ROOM) {
  424.     notify(player, "Only rooms may have parent rooms.");
  425.     return;
  426.   }
  427.  
  428.   /* everything is okay, do the change */
  429.   db[thing].zone = zone;
  430.   if (Typeof(thing) != TYPE_PLAYER) {
  431.     /* if the object is a player, resetting these flags is rather
  432.      * inconvenient -- although this may pose a bit of a security
  433.      * risk. Be careful when @chzone'ing wizard or royal players.
  434.      */
  435.     Flags(thing) &= ~WIZARD;
  436. #ifdef ROYALTY_FLAG
  437.     Flags(thing) &= ~ROYALTY;
  438. #endif
  439.     Flags(thing) &= ~INHERIT;
  440.     Powers(thing) = 0;               /* wipe out all powers */
  441.   }
  442.   notify(player, "Zone changed.");
  443. }
  444.  
  445. void do_attrib_flags(player, obj, atrname, flag)
  446.      dbref player;
  447.      char *obj;
  448.      char *atrname;
  449.      char *flag;
  450. {
  451.   dbref thing;
  452.   ATTR *attrib;
  453.   char *p;
  454.   int f;
  455.  
  456.   if ((thing = match_controlled(player, obj)) == NOTHING)
  457.     return;
  458.  
  459.   if (!flag || !*flag) {
  460.     notify(player, "What flag do you want to set?");
  461.     return;
  462.   }
  463.  
  464.   /* move past NOT token if there is one */
  465.   for (p = flag; *p && ((*p == NOT_TOKEN) || isspace(*p)); p++)
  466.     ;
  467.  
  468.   if (string_prefix("visual", p))
  469.     f = AF_ODARK;
  470.   else if (string_prefix("mortal_dark", p) && Hasprivs(player))
  471.     f = AF_MDARK;
  472.   else if (string_prefix("wizard", p) && Hasprivs(player))
  473.     f = AF_WIZARD;
  474.   else if (string_prefix("no_command", p))
  475.     f = AF_NOPROG;
  476.   else if (string_prefix("no_inherit", p))
  477.     f = AF_PRIVATE;
  478.   else if (string_prefix("no_clone", p))
  479.     f = AF_NOCOPY;
  480.   else {
  481.     notify(player, "Unrecognized attribute flag.");
  482.     return;
  483.   }
  484.  
  485.   /* find our attribute. Don't need to check permissions to set it, since
  486.    * we really can't do any harm even if the attribute is locked.
  487.    */
  488.   attrib = atr_get_noparent(thing, upcasestr(atrname));
  489.   if (!attrib) {
  490.     notify(player, "No such attribute to set.");
  491.     return;
  492.   }
  493.  
  494.   if (f == AF_ODARK) {
  495.     if (*flag == NOT_TOKEN)
  496.       attrib->flags |= f;
  497.     else
  498.       attrib->flags &= ~f;
  499.   } else {
  500.     if (*flag == NOT_TOKEN)
  501.       attrib->flags &= ~f;
  502.     else
  503.       attrib->flags |= f;
  504.   }
  505.     
  506.   notify(player, tprintf("%s - Set.", Name(thing)));
  507. }
  508.  
  509.  
  510. void do_set(player, name, flag)
  511.     dbref player;
  512.     const char *name;
  513.     const char *flag;
  514. {
  515.     dbref thing;
  516.     int res, her, listen;
  517.     char *p;
  518.     char tbuf1[BUFFER_LEN];
  519.  
  520.     /* check for attribute flag set first */
  521.     if ((p = (char *) index(name, '/')) != NULL) {
  522.     *p++ = '\0';
  523.     do_attrib_flags(player, name, p, flag);
  524.     return;
  525.     }
  526.  
  527.     /* find thing */
  528.     if ((thing = match_controlled(player, name)) == NOTHING)
  529.     return;
  530.     if (God(thing) && !God(player)) {
  531.     notify(player, "Only God can set himself!");
  532.     return;
  533.     }
  534. #ifdef INHERIT_FLAG
  535.     if (!Inherit(player) && Inherit(thing)) {
  536.     notify(player, "Authorization failed.");
  537.     return;
  538.     }
  539. #endif
  540. #ifdef DESTROY
  541.     /*
  542.      * The GOING flag can only be affected by set in one special case--A
  543.      * room that is set to be destroy may be saved.
  544.      */
  545.     if (string_prefix("!GOING", flag) &&
  546.     (Typeof(thing) == TYPE_ROOM) && (Flags(thing) & GOING)) {
  547.     Flags(thing) &= ~GOING;
  548.     if (Owner(thing) > 0)
  549.         notify(Owner(thing),
  550.            "Your room has been spared from destruction.");
  551.     return;
  552.     }
  553. #endif                /* DESTROY */
  554.     her = Hearer(thing);
  555.     listen = Listener(thing);
  556.  
  557.     /* check for attribute set first */
  558.     if ((p = (char *) index(flag, ':')) != NULL) {
  559.     ATTR *attrb = NULL;
  560.     ATTR *a = NULL;
  561.     *p++ = '\0';
  562.  
  563.     /* check for predefined attribute match */
  564.     attrb = atr_match(upcasestr(flag));
  565.     /* check for _. This is an attribute copy. */
  566.     if (*p == '_') {
  567.         dbref thing1;
  568.         char *q;
  569.  
  570.         q = (char *) index(p, '/');
  571.         if (! (q && *q)) {
  572.         notify(player, "I need an object and an attribute.");
  573.         return;
  574.         }
  575.         *q++ = '\0';
  576.         init_match(player, p + 1, NOTYPE); /* not p. Name shouldn't have to
  577.                         * to start with an underscore.
  578.                         */
  579.         match_everything();
  580.         if ((thing1 = noisy_match_result()) == NOTHING)
  581.         return;
  582.         if ((a = atr_get_noparent(thing1, upcasestr(q))) == NULL) {
  583.         notify(player, "No such attribute.");
  584.         return;
  585.         }
  586.         strcpy(tbuf1, uncompress(a->value));
  587.     } else {
  588.         strcpy(tbuf1, p);
  589.     }
  590.     if (attrb) {
  591.         if (!strcmp(attrb->name, "ALIAS")) {
  592.         do_alias(player, thing, attrb, tbuf1);
  593.         return;
  594.         }
  595.         if (!Can_Write_Attr(player, thing, attrb)) {
  596.         notify(player, "Sorry, you cannot modify that.");
  597.         return;
  598.         }
  599.         res = atr_add(thing, attrb->name, tbuf1, player, attrb->flags);
  600.         if (!res) {
  601.         notify(player, "No such attribute to reset.");
  602.         return;
  603.         }
  604.         if (res == -1) {
  605.         notify(player, "That attribute cannot be changed by you.");
  606.         return;
  607.         }
  608.     } else {
  609.         res = atr_add(thing, upcasestr(flag), tbuf1, player, NOTHING);
  610.         if (!res) {
  611.         notify(player, "No such attribute to reset.");
  612.         return;
  613.         }
  614.         if (res == -1) {
  615.         notify(player, "That attribute cannot be changed by you.");
  616.         return;
  617.         }
  618.     }
  619.  
  620.     /* one special case for listen */
  621.     if (attrb && !strcmp(attrb->name, "LISTEN")) {
  622.         if (GoodObject(Location(thing))) {
  623.         if (!*p && !listen && !Hearer(thing)) {
  624.             notify_except(Contents(Location(thing)), thing,
  625.                  tprintf("%s loses its ears and becomes deaf.",
  626.                      Name(thing)));
  627.         } else if (*p && !her && !listen)
  628.             notify_except(Contents(Location(thing)), thing,
  629.                   tprintf("%s grows ears and can now hear.", 
  630.                       Name(thing)));
  631.         }
  632.     }
  633.  
  634.     /* automatically set the STARTUP flag if appropriate */
  635.     if (attrb && !strcmp(attrb->name, "STARTUP")) {
  636.         if (*p)
  637.         Flags(thing) |= STARTUP;
  638.         else
  639.         Flags(thing) &= ~STARTUP;
  640.     }
  641.  
  642.     if (!Quiet(player) && !Quiet(thing)) 
  643.         notify(player, tprintf("%s - Set.", Name(thing)));
  644.     return;
  645.     }
  646.  
  647.     /* we haven't set an attribute, so we must be setting a flag */
  648.  
  649.     /* move p past NOT_TOKEN if present */
  650.     for (p = (char *) flag; *p && (*p == NOT_TOKEN || isspace(*p)); p++) ;
  651.  
  652.     /* identify flag */
  653.     if (*p == '\0') {
  654.     notify(player, "You must specify a flag to set.");
  655.     return;
  656.     }
  657.     set_flag(player, thing, p, (*flag == NOT_TOKEN) ? 1 : 0, her, listen);
  658. }
  659.  
  660.  
  661. void do_cpattr(player, oldpair, newpair)
  662.      dbref player;
  663.      char *oldpair;
  664.      char *newpair[];
  665. {
  666.   /* the command is of the format:
  667.    * @cpattr oldobj/oldattr = newobj1/newattr1, newobj2/newattr2, etc.
  668.    */
  669.  
  670.   dbref oldobj;
  671.   char tbuf1[BUFFER_LEN];
  672.   int i;
  673.   char *p;
  674.   ATTR *a;
  675.   char *text;
  676.  
  677.   /* must copy from something */
  678.   if (!oldpair || !*oldpair) {
  679.     notify(player, "What do you want to copy from?");
  680.     return;
  681.   }
  682.  
  683.   /* find the old object */
  684.   strcpy(tbuf1, oldpair);
  685.   p = (char *) index(tbuf1, '/');
  686.   if (!p || !*p) {
  687.     notify(player, "What object do you want to copy the attribute from?");
  688.     return;
  689.   }
  690.   *p++ = '\0';
  691.   init_match(player, tbuf1, NOTYPE);
  692.   match_everything();
  693.   oldobj = noisy_match_result();
  694.   if (oldobj == NOTHING)
  695.     return;
  696.   
  697.   /* find the old attribute */
  698.   a = atr_get_noparent(oldobj, upcasestr(p));
  699.   if (!a) {
  700.     notify(player, "No such attribute to copy from.");
  701.     return;
  702.   } 
  703.   /* check permissions to get it */
  704.   if (!Can_Read_Attr(player, oldobj, a)) {
  705.     notify(player, "Permission to read attribute denied.");
  706.     return;
  707.   }
  708.  
  709.   /* we can read it. Copy the value. */
  710.   text = safe_uncompress(a->value);
  711.  
  712.   /* now we loop through our new object pairs and copy, calling @set. */
  713.   for (i = 1; i < MAX_ARG && (newpair[i] != NULL); i++) {
  714.     if (!*newpair[i]) {
  715.       notify(player, "What do you want to copy to?");
  716.     } else {
  717.       strcpy(tbuf1, newpair[i]);
  718.       p = (char *) index(tbuf1, '/');
  719.       if (!p || !*p) {
  720.     notify(player, "What object do you want to copy the attribute to?");
  721.       } else {
  722.     *p++ = '\0';
  723.     do_set(player, tbuf1, tprintf("%s:%s", p, text));
  724.       }
  725.     }
  726.   }
  727.  
  728.   free(text);            /* safe_uncompress malloc()s memory */
  729.   notify(player, "Attributes copied.");
  730. }
  731.   
  732.  
  733. void do_gedit(player, it, argv)
  734.     dbref player;
  735.     char *it;
  736.     char *argv[];
  737. {
  738.   ALIST *a;
  739.   dbref thing;
  740.   char tbuf1[BUFFER_LEN];
  741.   char *p, *q;
  742.   ATTR *attrib;
  743.   int is_wild = 0;
  744.  
  745.   if(!(it && *it)) {
  746.     notify(player, "I need to know what you want to edit.");
  747.     return;
  748.   }
  749.   strcpy(tbuf1, it);
  750.   q = (char *) index(tbuf1, '/');
  751.   if (!(q && *q)) {
  752.     notify(player, "I need to know what you want to edit.");
  753.     return;
  754.   }
  755.   *q++ = '\0';
  756.   init_match(player, tbuf1, NOTYPE);
  757.   match_everything();
  758.   thing = noisy_match_result();
  759.  
  760.   if ((thing == NOTHING) || !controls(player, thing)) {
  761.     notify(player, "Permission denied.");
  762.     return;
  763.   }
  764.   if(*q == '_') q++;
  765.  
  766.   if (!argv[1] || !*argv[1]) {
  767.     notify(player, "Nothing to do.");
  768.     return;
  769.   }
  770.  
  771.   /* first let's check for wildcard characters */
  772.   for (p = q; *p && !is_wild; p++)
  773.     if ((*p == '*') || (*p == '?'))
  774.       is_wild = 1;
  775.   
  776.   if (!is_wild) {
  777.     /* we only have one attribute. Check for possible abbreviation,
  778.      * then edit that the attribute with that name.
  779.      */
  780.     attrib = atr_match(upcasestr(q));
  781.     if (attrib)
  782.       do_edit(player, thing, attrib->name, argv);
  783.     else
  784.       do_edit(player, thing, q, argv);
  785.   } else {
  786.     /* we've got a wildcard, treat like old @gedit */
  787.     for(a = db[thing].list; a; a = AL_NEXT(a))
  788.       if(!AL_BAD(a) && wild_match(q, AL_NAME(a))) 
  789.     do_edit(player, thing, AL_NAME(a), argv);
  790.   }
  791. }
  792.  
  793. void do_edit(player, thing, q, argv)
  794.      dbref player;
  795.      dbref thing;
  796.      char *q;            /* attribute name */
  797.      char *argv[];
  798. {
  799.   int d, len, res;
  800.   ATTR *a;
  801.   char *r, *s , *val;
  802.   char tbuf1[BUFFER_LEN];
  803.  
  804.   val = argv[1];
  805.   r = (argv[2]) ? argv[2] : (char *) "";
  806.  
  807.   a = atr_get_noparent(thing, q);
  808.   if(!a) {
  809.     notify(player, "No such attribute, try set instead.");
  810.     return;
  811.   }
  812.   if ((a->flags & AF_LOCKED) && (Owner(player) != Owner(a->creator))) {
  813.     notify(player, "You need to control an attribute to edit it.");
  814.     return;
  815.   }
  816.  
  817.   s = (char *) uncompress(a->value); /* warning: pointer to static buffer */
  818.  
  819.   if (!strcmp(val, "$")) {
  820.     /* append */
  821.     if (strlen(s) + strlen(r) < BUFFER_LEN) {
  822.       strcpy(tbuf1, s);
  823.       strcat(tbuf1, r);
  824.     }
  825.   } else if (!strcmp(val, "^")) {
  826.     /* prepend */
  827.     if (strlen(s) + strlen(r) < BUFFER_LEN) {
  828.       strcpy(tbuf1, r);
  829.       strcat(tbuf1, s);
  830.     }
  831.   } else {
  832.     /* find and replace */
  833.     len = strlen(val);
  834.     for (d = 0; (d < BUFFER_LEN) && *s;)
  835.       if (strncmp(val, s, len) == 0) {
  836.     if ((d + strlen(r)) < BUFFER_LEN) {
  837.       strcpy(tbuf1 + d, r);
  838.       d += strlen(r);
  839.       s += len;
  840.     } else
  841.       tbuf1[d++] = *s++;
  842.       } else
  843.     tbuf1[d++] = *s++;
  844.     tbuf1[d++] = 0;
  845.   }
  846.  
  847.   res = atr_add(thing, a->name, tbuf1, player, NOTHING);
  848.   if(!res) {
  849.     notify(player, "That attribute seems to have vanished!");
  850.     return;
  851.   }
  852.   if(res == -1) {
  853.     notify(player, "You don't have the power to change that.");
  854.     return;
  855.   }
  856.   if(!Quiet(player) && !Quiet(thing))
  857.     notify(player, tprintf("%s - Set: %s", a->name, tbuf1));
  858. }
  859.  
  860. void do_trigger(player, object, argv)
  861.     dbref player;
  862.     char *object;
  863.     char *argv[];
  864. {
  865.   dbref thing;
  866.   int a;
  867.   char *s;
  868.   char tbuf1[BUFFER_LEN];
  869.  
  870.   strcpy(tbuf1, object);
  871.   for(s = tbuf1; *s && (*s != '/'); s++);
  872.   if(!*s) {
  873.     notify(player, "I need to know what attribute to trigger.");
  874.     return;
  875.   }
  876.   *s++ = '\0';
  877.  
  878.   init_match(player, tbuf1, NOTYPE);
  879.   match_everything();
  880.   thing = noisy_match_result();
  881.  
  882.   if(thing == NOTHING) return;
  883.  
  884.   if (!controls(player, thing)) {
  885.     notify(player, "Permission denied.");
  886.     return;
  887.   }
  888.  
  889.   if (God(thing) && !God(player)) {
  890.     notify(player, "You can't trigger God!");
  891.     return;
  892.   }
  893.  
  894. #ifdef INHERIT_FLAG
  895.   if ((!Inherit(player) && Inherit(thing)) && !LinkOk(thing)) {
  896.     notify(player, "Authorization failed.");
  897.     return;
  898.   }
  899. #endif
  900.  
  901.   /* trigger modifies the stack */
  902.   for (a = 0; a < 10; a++)
  903.     wptr[a] = argv[a + 1];
  904.  
  905.   /* we need to call did_it because trigger uses a charge */
  906.   did_it(player, thing, NULL, NULL, NULL, NULL, upcasestr(s), NOTHING);
  907.   if(!Quiet(player) && !Quiet(thing))
  908.     notify(player, tprintf("%s - Triggered.", Name(thing)));
  909. }
  910.  
  911.  
  912. /* for lack of a better place, the use code is here */
  913.  
  914. void do_use(player, what)
  915.      dbref player;
  916.      const char *what;
  917. {
  918.   dbref thing;
  919.  
  920.   /* find it */
  921.  
  922.   init_match(player, what, TYPE_THING);
  923.   match_near_things();
  924.  
  925.   /* if we pass the use key, do it */
  926.  
  927.   if ((thing = noisy_match_result()) != NOTHING) {
  928.     if (!eval_boolexp(player, db[thing].usekey, thing, 0, USELOCK)) {
  929.       notify(player, "Permission denied.");
  930.       return;
  931.     } else
  932.       did_it(player, thing, "USE", "Used.", "OUSE", NULL, "AUSE", NOTHING);
  933.   }
  934. }
  935.  
  936. void do_parent(player, name, parent_name)
  937.      dbref player;
  938.      char *name;
  939.      char *parent_name;
  940. {
  941.   dbref thing;
  942.   dbref parent;
  943.   dbref check;
  944.   int i;
  945.  
  946.   init_match(player, name, NOTYPE);
  947.   match_nearby();
  948.   if ((thing = noisy_match_result()) == NOTHING)
  949.     return;
  950.  
  951.   /* players may not be parented */
  952.   if (Typeof(thing) == TYPE_PLAYER) {
  953.     notify(player, "Don't you like your biological parents?");
  954.     return;
  955.   }
  956.  
  957.   if (!parent_name || !*parent_name || !strcasecmp(parent_name, "none"))
  958.     parent = NOTHING;
  959.   else {
  960.     init_match(player, parent_name, NOTYPE);
  961.     match_everything();
  962.     if ((parent = noisy_match_result()) == NOTHING)
  963.       return;
  964.   }
  965.  
  966.   /* do control check */
  967.   if (!controls(player, thing)) {
  968.     notify(player, "Permission denied.");
  969.     return;
  970.   }
  971.  
  972.   /* a player may change an object's parent to NOTHING or to an 
  973.    * object he owns, or one that is LINK_OK.
  974.    */
  975.   if ((parent != NOTHING) && !Wizard(player) &&
  976.       !Owns(player, parent) && !LinkOk(parent)) {
  977.     notify(player, "Permission denied.");
  978.     return;
  979.   }
  980.  
  981.   /* check to make sure no recursion can happen */
  982.   if (parent == thing) {
  983.     notify(player, "A thing cannot be its own ancestor!");
  984.     return;
  985.   }
  986.   if (parent != NOTHING) {
  987.     for (i = 0, check = Parent(parent); 
  988.      (i < MAX_PARENTS) && (check != NOTHING);
  989.      i++, check = Parent(check)) {
  990.       if (check == thing) {
  991.     notify(player, "You are not allowed to be your own ancestor!");
  992.     return;
  993.       }
  994.     }
  995.     if (i >= MAX_PARENTS) {
  996.       notify(player, "Too many ancestors.");
  997.       return;
  998.     }
  999.   }
  1000.  
  1001.   /* everything is okay, do the change */
  1002.   db[thing].parent = parent;
  1003.   notify(player, "Parent changed.");
  1004. }
  1005.  
  1006. void do_wipe(player, name)
  1007.      dbref player;
  1008.      char *name;
  1009. {
  1010.   /* obliterate all attribute from an object */
  1011.  
  1012.   dbref thing;
  1013.   ALIST *a;
  1014.  
  1015.   init_match(player, name, NOTYPE);
  1016.   match_nearby();
  1017.   if ((thing = noisy_match_result()) == NOTHING)
  1018.     return;
  1019.  
  1020.   /* this is too destructive of a command to be used by someone who
  1021.    * doesn't own the object. Thus, the check is on Owns not controls.
  1022.    */
  1023.   if (!Wizard(player) && !Owns(player, thing)) {
  1024.     notify(player, "Permission denied.");
  1025.     return;
  1026.   }
  1027.  
  1028.   /* protect SAFE objects */
  1029.   if (Safe(thing)) {
  1030.     notify(player, "That object is protected.");
  1031.     return;
  1032.   }
  1033.  
  1034.   /* for added security, only God can modify wiz-only-modifiable
  1035.    * attributes using his command. Also, you cannot wipe attributes
  1036.    * that you do not control.
  1037.    */
  1038.   for (a = db[thing].list; a; a = AL_NEXT(a)) {
  1039.     if (AL_BAD(a) ||
  1040.     ((AL_FLAGS(a) & AF_WIZARD) && !God(player)) ||
  1041.     ((AL_FLAGS(a) & AF_LOCKED) && 
  1042.      (Owner(player) != Owner(AL_CREATOR(a)))))
  1043.       continue;
  1044.     atr_add(thing, AL_NAME(a), "", player, NOTHING);
  1045.   }
  1046.  
  1047.   notify(player, "Attributes wiped.");
  1048. }
  1049.